/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.common.reflect;


import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * 缓存Java class的Java Bean信息类
 * CachedIntrospectionResults
 *
 * @author vacoor
 * @see java.beans.PropertyDescriptor
 * @see java.beans.Introspector
 * @deprecated
 */
@Deprecated
public class Introspectors {
    private static final Map<Class<?>, Object> classCache = new WeakHashMap<Class<?>, Object>();

    public static Introspectors from(Class<?> beanClass) throws IntrospectionException {
        Introspectors results;
        Object value = classCache.get(beanClass);
        if (value instanceof Reference) {
            Reference ref = (Reference) value;
            results = (Introspectors) ref.get();
        } else {
            results = (Introspectors) classCache.get(beanClass);
        }

        if (results == null) {
            results = new Introspectors(beanClass);
            classCache.put(beanClass, new WeakReference<Introspectors>(results));
        }
        return results;
    }

    private final BeanInfo beanInfo;
    private final Map<String, PropertyDescriptor> propertyDescriptorCache;

    private Introspectors(Class<?> beanClass) throws IntrospectionException {
        beanInfo = Introspector.getBeanInfo(beanClass);
        propertyDescriptorCache = new LinkedHashMap<String, PropertyDescriptor>();

        PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : pds) {
            if (Class.class.equals(beanClass) && "classLoader".equals(pd.getName())) {
                //Ignore Class.getClassLoader(); getClass()
                continue;
            }
            this.propertyDescriptorCache.put(pd.getName(), pd);
        }
    }

    public BeanInfo getBeanInfo() {
        return this.beanInfo;
    }

    public Class getBeanClass() {
        return this.beanInfo.getBeanDescriptor().getBeanClass();
    }

    public PropertyDescriptor getPropertyDescriptor(String property) {
        return propertyDescriptorCache.get(property);
    }

    public PropertyDescriptor[] getPropertyDescriptors() {
        return propertyDescriptorCache.values().toArray(new PropertyDescriptor[propertyDescriptorCache.size()]);
    }

    public PropertyDescriptor[] getPropertyDescriptors(String[] ignoreProperties) {
        LinkedHashMap<String, PropertyDescriptor> pds = new LinkedHashMap<String, PropertyDescriptor>(propertyDescriptorCache);
        for (String p : ignoreProperties) {
            pds.remove(p);
        }
        return pds.values().toArray(new PropertyDescriptor[pds.size()]);
    }
}
